package com.lightsaber.trade.cloth.service.archive.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;

import com.lightsaber.trade.cloth.dao.archive.ArchivedImageDao;
import com.lightsaber.trade.cloth.dao.planning.Level2PlanningDao;
import com.lightsaber.trade.cloth.dao.planning.Level3PlanningDao;
import com.lightsaber.trade.cloth.dao.planning.PlanningDao;
import com.lightsaber.trade.cloth.dao.planning.ProgrammePlanningItemDao;
import com.lightsaber.trade.cloth.dao.planning.ResourceGroupDao;
import com.lightsaber.trade.cloth.dao.planning.ResourceGroupItemDao;
import com.lightsaber.trade.cloth.entity.archive.ArchivedImage;
import com.lightsaber.trade.cloth.entity.category.Category;
import com.lightsaber.trade.cloth.entity.planning.Level2Planning;
import com.lightsaber.trade.cloth.entity.planning.Level3Planning;
import com.lightsaber.trade.cloth.entity.planning.Planning;
import com.lightsaber.trade.cloth.entity.planning.PlanningLevel;
import com.lightsaber.trade.cloth.entity.planning.ProgrammePlanningItem;
import com.lightsaber.trade.cloth.entity.planning.ResourceGroup;
import com.lightsaber.trade.cloth.entity.planning.ResourceGroupItem;
import com.lightsaber.trade.cloth.service.archive.ArchiveImageService;
import com.lightsaber.trade.cloth.service.archive.DuplicateNameException;

@Service
@Component
@Transactional
public class ArchiveImageServiceImpl implements ArchiveImageService {
    @Autowired
    private PlanningDao planningDao;

    @Autowired
    private Level2PlanningDao level2PlanningDao;

    @Autowired
    private Level3PlanningDao level3PlanningDao;

    @Autowired
    private ProgrammePlanningItemDao programmePlanningItemDao;

    @Autowired
    private ResourceGroupDao resourceGroupDao;

    @Autowired
    private ResourceGroupItemDao resourceGroupItemDao;

    @Autowired
    private ArchivedImageDao archivedImageDao;

    @Override
    public ArchivedImage get(final String id) {
        return archivedImageDao.get(id);
    }

    @Override
    public Page<Planning> findPage(final Planning planning, final Page<Planning> page) {
        return planningDao.findPage(planning, page);
    }

    private void validate(final ArchivedImage archivedImage) throws DuplicateNameException {
        List<ArchivedImage> existList = archivedImageDao.findAllByName(archivedImage.getName());
        if (!existList.isEmpty()) {
            throw new DuplicateNameException();
        }
    }

    @Override
    public void archiveImage(final Planning planning, final ArchivedImage archivedImage)
            throws DuplicateNameException {

        validate(archivedImage);

        Planning planningNew = new Planning();

        // planningNew.setCategory(planning.getCategory());
        planningNew.setEndorsedDate(planning.getEndorsedDate());
        planningNew.setIsArchivedImage(true);
        planningNew.setPlanningLevel(planning.getPlanningLevel());
        planningNew.setStatus(planning.getStatus());

        planningDao.save(planningNew);

        // level2
        if (planning.getPlanningLevel() == PlanningLevel.SecondLevel) {
            copyPlanningLevel2(planning, planningNew, false, null);
        } else {// level3
            // copy level2 before copy level3 (level2 and level3 belong to same
            // category)
            // copy level2
            // find planning, according to category id and level2
            Planning planning2 = planningDao.findByCategoryIdAndLevel(planning.getCategory()
                    .getId(), PlanningLevel.SecondLevel);
            if (planning2 != null) {
                Planning planning2New = new Planning();
                planning2New.setEndorsedDate(planning2.getEndorsedDate());
                planning2New.setIsArchivedImage(true);
                planning2New.setPlanningLevel(planning2.getPlanningLevel());
                planning2New.setStatus(planning2.getStatus());
                planningDao.save(planning2New);
                Map<String, String> PlanningItemOldMapNew = new HashMap<String, String>();
                // copy level2
                copyPlanningLevel2(planning2, planning2New, true, PlanningItemOldMapNew);
                // copy level3
                Level3Planning level3PlanningOld = planning.getLevel3Planning();
                Level3Planning level3PlanningNew = new Level3Planning();

                level3PlanningNew.setPlanning(planningNew);
                level3PlanningNew.setPlanningExercise(level3PlanningOld.getPlanningExercise());
                level3PlanningNew.setRemarks(level3PlanningOld.getRemarks());

                level3PlanningDao.save(level3PlanningNew);

                List<ResourceGroup> groups = level3PlanningOld.getResourceGroups();
                for (ResourceGroup group : groups) {
                    // ProgrammePlanningItem : ResourceGroup many to one
                    // ProgrammePlanningItem
                    ProgrammePlanningItem item = group.getProgrammePlanningItem();
                    /*
                     * ProgrammePlanningItem newItem = new
                     * ProgrammePlanningItem();
                     * newItem.setOfferingCampus(item.getOfferingCampus());
                     * newItem.setPlannedPlacesNew(item.getPlannedPlacesNew());
                     * newItem
                     * .setPlannedPlacesProg(item.getPlannedPlacesProg());
                     * newItem
                     * .setPlannedPlacesTotal(item.getPlannedPlacesTotal());
                     * newItem.setPlanYear(item.getPlanYear());
                     * newItem.setStudyYear(item.getStudyYear()); // save
                     * ProgrammePlanningItem
                     * programmePlanningItemDao.save(newItem);
                     */
                    // new ResourceGroup
                    ResourceGroup groupNew = new ResourceGroup();
                    groupNew.setName(group.getName());
                    groupNew.setPlace(group.getPlace());
                    // according old item get (when level 2 copy) create new
                    // item
                    ProgrammePlanningItem newItem = programmePlanningItemDao
                            .get(PlanningItemOldMapNew.get(item.getId()));
                    groupNew.setProgrammePlanningItem(newItem);
                    groupNew.setLevel3Planning(level3PlanningNew);
                    // save resourceGroup
                    resourceGroupDao.save(groupNew);

                    // ResourceGroupItem
                    List<ResourceGroupItem> groupItems = group.getResourceGroupItems();
                    for (ResourceGroupItem groupItem : groupItems) {
                        ResourceGroupItem groupItemNew = new ResourceGroupItem();
                        groupItemNew.setCurriculumHours(groupItem.getCurriculumHours());
                        groupItemNew.setDistribution(groupItem.getDistribution());
                        groupItemNew.setServingCampus(groupItem.getServingCampus());
                        groupItemNew.setServingDept(groupItem.getServingDept());
                        groupItemNew.setResourceGroup(groupNew);
                        // save ResourceGroupItem
                        resourceGroupItemDao.save(groupItemNew);
                    }
                }
            }
        }
        // save archive image
        archivedImage.setCategory(planning.getCategory());
        archivedImage.setPlanning(planningNew);
        archivedImageDao.save(archivedImage);

    }

    private void copyPlanningLevel2(final Planning planning, final Planning planningNew,
            final boolean isUseForLevel3, final Map<String, String> PlanningItemOldMapNew) {

        Level2Planning level2PlanningOld = planning.getLevel2Planning();
        Level2Planning level2PlanningNew = new Level2Planning();

        level2PlanningNew.setPlanning(planningNew);
        level2PlanningNew.setPlanningExercise(level2PlanningOld.getPlanningExercise());
        level2PlanningNew.setRemarks(level2PlanningOld.getRemarks());

        level2PlanningDao.save(level2PlanningNew);

        List<ProgrammePlanningItem> items = level2PlanningOld.getProgrammePlanningItems();

        for (ProgrammePlanningItem item : items) {
            ProgrammePlanningItem newItem = new ProgrammePlanningItem();
            newItem.setLevel2Planning(level2PlanningNew);
            newItem.setCode(item.getCode());
            newItem.setOperatingCampus(item.getOperatingCampus());
            newItem.setOperatingUnit(item.getOperatingUnit());
            newItem.setPlannedPlacesNew(item.getPlannedPlacesNew());
            newItem.setPlannedPlacesProg(item.getPlannedPlacesProg());
            newItem.setPlannedPlacesNewActual(item.getPlannedPlacesNewActual());
            newItem.setPlannedPlacesProgActual(item.getPlannedPlacesProgActual());
            newItem.setPlanYear(item.getPlanYear());
            newItem.setStudyYear(item.getStudyYear());
            programmePlanningItemDao.save(newItem);
            if (isUseForLevel3) {
                PlanningItemOldMapNew.put(item.getId(), newItem.getId());
            }
        }
    }

    @Override
    public List<ArchivedImage> getByPlanningExercise(final Category category) {
        return archivedImageDao.getByPlanningExercise(category);
    }

}
